/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.knox.gateway.config;

import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.security.KeyStore;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public interface GatewayConfig {

  // Used as the basis for any home directory that is not specified.
  String GATEWAY_HOME_VAR = "GATEWAY_HOME";

  /**
   * Variable name for the location of configuration files edited by users
   *
   * @deprecated use {@link GatewayConfig#KNOX_GATEWAY_CONF_DIR_VAR} instead
   */
  @Deprecated
  String GATEWAY_CONF_HOME_VAR = "GATEWAY_CONF_HOME";

  String KNOX_GATEWAY_CONF_DIR_VAR = "KNOX_GATEWAY_CONF_DIR";

  /**
   * Variable name for the location of data files generated by the gateway at runtime.
   *
   * @deprecated use {@link GatewayConfig#KNOX_GATEWAY_DATA_DIR} instead
   */
  @Deprecated
  String GATEWAY_DATA_HOME_VAR = "GATEWAY_DATA_HOME";

  String KNOX_GATEWAY_DATA_DIR = "KNOX_GATEWAY_DATA_DIR";

  String GATEWAY_CONFIG_ATTRIBUTE = "org.apache.knox.gateway.config";
  String HADOOP_KERBEROS_SECURED = "gateway.hadoop.kerberos.secured";
  String KRB5_CONFIG = "java.security.krb5.conf";
  String KRB5_DEBUG = "sun.security.krb5.debug";
  String KRB5_LOGIN_CONFIG = "java.security.auth.login.config";
  String KRB5_USE_SUBJECT_CREDS_ONLY = "javax.security.auth.useSubjectCredsOnly";

  String IDENTITY_KEYSTORE_PASSWORD_ALIAS = "gateway.tls.keystore.password.alias";
  String IDENTITY_KEYSTORE_PATH = "gateway.tls.keystore.path";
  String IDENTITY_KEYSTORE_TYPE = "gateway.tls.keystore.type";
  String IDENTITY_KEY_ALIAS = "gateway.tls.key.alias";
  String IDENTITY_KEY_PASSPHRASE_ALIAS = "gateway.tls.key.passphrase.alias";
  String DEFAULT_IDENTITY_KEYSTORE_TYPE = KeyStore.getDefaultType();
  String DEFAULT_IDENTITY_KEYSTORE_PASSWORD_ALIAS = "gateway-identity-keystore-password";
  String DEFAULT_IDENTITY_KEY_ALIAS = "gateway-identity";
  String DEFAULT_IDENTITY_KEY_PASSPHRASE_ALIAS = "gateway-identity-passphrase";
  String DEFAULT_GATEWAY_KEYSTORE_NAME = "gateway.jks";

  String SIGNING_KEYSTORE_NAME = "gateway.signing.keystore.name";
  String SIGNING_KEYSTORE_PASSWORD_ALIAS = "gateway.signing.keystore.password.alias";
  String SIGNING_KEYSTORE_TYPE = "gateway.signing.keystore.type";
  String SIGNING_KEY_ALIAS = "gateway.signing.key.alias";
  String SIGNING_KEY_PASSPHRASE_ALIAS = "gateway.signing.key.passphrase.alias";
  String DEFAULT_SIGNING_KEYSTORE_PASSWORD_ALIAS = "signing.keystore.password";
  String DEFAULT_SIGNING_KEYSTORE_TYPE = KeyStore.getDefaultType();
  String DEFAULT_SIGNING_KEY_ALIAS = "gateway-identity";
  String DEFAULT_SIGNING_KEY_PASSPHRASE_ALIAS = "signing.key.passphrase";

  String GATEWAY_TRUSTSTORE_PASSWORD_ALIAS = "gateway.truststore.password.alias";
  String GATEWAY_TRUSTSTORE_PATH = "gateway.truststore.path";
  String GATEWAY_TRUSTSTORE_TYPE = "gateway.truststore.type";
  String DEFAULT_GATEWAY_TRUSTSTORE_TYPE = KeyStore.getDefaultType();
  String DEFAULT_GATEWAY_TRUSTSTORE_PASSWORD_ALIAS = "gateway-truststore-password";

  String HTTP_CLIENT_TRUSTSTORE_PASSWORD_ALIAS = "gateway.httpclient.truststore.password.alias";
  String HTTP_CLIENT_TRUSTSTORE_PATH = "gateway.httpclient.truststore.path";
  String HTTP_CLIENT_TRUSTSTORE_TYPE = "gateway.httpclient.truststore.type";
  String DEFAULT_HTTP_CLIENT_TRUSTSTORE_TYPE = KeyStore.getDefaultType();
  String DEFAULT_HTTP_CLIENT_TRUSTSTORE_PASSWORD_ALIAS = "gateway-httpclient-truststore-password";

  String CREDENTIAL_STORE_ALG = "gateway.credential.store.alg";
  String DEFAULT_CREDENTIAL_STORE_ALG = "AES";
  String CREDENTIAL_STORE_TYPE = "gateway.credential.store.type";
  String DEFAULT_CREDENTIAL_STORE_TYPE = "JCEKS";

  String REMOTE_CONFIG_REGISTRY_TYPE = "type";
  String REMOTE_CONFIG_REGISTRY_ADDRESS = "address";
  String REMOTE_CONFIG_REGISTRY_NAMESPACE = "namespace";
  String REMOTE_CONFIG_REGISTRY_AUTH_TYPE = "authType";
  String REMOTE_CONFIG_REGISTRY_PRINCIPAL = "principal";
  String REMOTE_CONFIG_REGISTRY_CREDENTIAL_ALIAS = "credentialAlias";
  String REMOTE_CONFIG_REGISTRY_KEYTAB = "keytab";
  String REMOTE_CONFIG_REGISTRY_USE_KEYTAB = "useKeyTab";
  String REMOTE_CONFIG_REGISTRY_USE_TICKET_CACHE = "useTicketCache";
  /* If true ensures that the auth scheme used to create znodes is `auth` and not `sasl` */
  String ZOOKEEPER_REMOTE_CONFIG_REGISTRY_BACKWARDS_COMPATIBLE = "backwardsCompatible";

  String PROXYUSER_SERVICES_IGNORE_DOAS = "gateway.proxyuser.services.ignore.doas";

  /**
   * The location of the gateway configuration.
   * Subdirectories will be: topologies
   * @return The location of the gateway configuration.
   */
  String getGatewayConfDir();

  /**
   * The location of the gateway runtime generated data.
   * Subdirectories will be security, deployments
   * @return The location of the gateway runtime generated data.
   */
  String getGatewayDataDir();

  /**
   * The location of the gateway services definition's root directory
   * @return The location of the gateway services top level directory.
   */
  String getGatewayServicesDir();

  /**
   * The location of the gateway applications's root directory
   * @return The location of the gateway applications top level directory.
   */
  String getGatewayApplicationsDir();

  String getHadoopConfDir();

  String getGatewayHost();

  int getGatewayPort();

  String getGatewayPath();

  String getGatewayProvidersConfigDir();

  String getGatewayDescriptorsDir();

  String getGatewayTopologyDir();

  String getGatewaySecurityDir();

  /**
   * Returns the path to the Gateway's keystore directory
   * <p>
   * This path is generally calculated to be a subdirectory named "keystores" under the configured
   * "security" directory. However, it may be possible for it to be configured as something else.
   *
   * @return the path to the Gateway's keystore directory
   */
  String getGatewayKeystoreDir();

  String getGatewayDeploymentDir();

  InetSocketAddress getGatewayAddress() throws UnknownHostException;

  boolean isSSLEnabled();

  List<String> getExcludedSSLProtocols();

  List<String> getIncludedSSLCiphers();

  List<String> getExcludedSSLCiphers();

  boolean isHadoopKerberosSecured();

  String getKerberosConfig();

  boolean isKerberosDebugEnabled();

  String getKerberosLoginConfig();

  String getDefaultTopologyName();

  String getDefaultAppRedirectPath();

  String getFrontendUrl();

  boolean isClientAuthNeeded();

  boolean isClientAuthWanted();

  String getTruststorePath();

  boolean getTrustAllCerts();

  String getKeystoreType();

  String getTruststoreType();

  /**
   * Returns the configured value for the alias name to use when to looking up the Gateway's
   * truststore password.
   *
   * @return an alias name
   */
  String getTruststorePasswordAlias();

  boolean isXForwardedEnabled();

  String getEphemeralDHKeySize();

  int getHttpClientMaxConnections();

  int getHttpClientConnectionTimeout();

  int getHttpClientSocketTimeout();

  /**
   * Returns the configured value for the path to the truststore to be used by the HTTP client instance
   * connecting to a service from the Gateway.
   *
   * @return a path to the trust file; or <code>null</code> if not set
   */
  String getHttpClientTruststorePath();

  /**
   * Returns the configured value for the type of the truststore specified by {@link #getHttpClientTruststorePath()}.
   *
   * @return a truststore type
   */
  String getHttpClientTruststoreType();

  /**
   * Returns the configured value for the alias name to use when to looking up the HTTP client's
   * truststore password.
   *
   * @return an alias name
   */
  String getHttpClientTruststorePasswordAlias();

  /**
   * @return the algorithm that is used when creating a SecretKey when adding an
   *         alias into a credential store
   */
  String getCredentialStoreAlgorithm();

  /**
   * @return the type of the credential store used by AliasService
   */
  String getCredentialStoreType();

  int getThreadPoolMax();

  int getHttpServerRequestBuffer();

  int getHttpServerRequestHeaderBuffer();

  int getHttpServerResponseBuffer();

  int getHttpServerResponseHeaderBuffer();

  int getGatewayDeploymentsBackupVersionLimit();

  long getGatewayDeploymentsBackupAgeLimit();

  long getGatewayIdleTimeout();

  /**
   * Returns the configured value for the path to the keystore holding the key and certificate for the
   * Gateway's TLS identity.
   *
   * @return a path to the keystore file; or <code>null</code> if not set
   */
  String getIdentityKeystorePath();

  /**
   * Returns the configured value for the type of the keystore holding the Gateway's identity.
   *
   * @return a keystore type
   */
  String getIdentityKeystoreType();

  /**
   * Returns the configured value for the alias name to use when to looking up the Gateway's identity
   * keystore's password.
   *
   * @return an alias name
   */
  String getIdentityKeystorePasswordAlias();

  /**
   * Returns the configured value for the alias name to use when to looking up the Gateway's identity
   * from the Gateway's identity keystore.
   *
   * @return an alias name
   */
  String getIdentityKeyAlias();

  /**
   * Returns the configured value for the alias name to use when to looking up the Gateway's identity
   * key's password.
   *
   * @return an alias name
   */
  String getIdentityKeyPassphraseAlias();

  String getSigningKeystoreName();

  /**
   * Returns the calculated value for the path to the keystore holding the key and certificate for the
   * Gateway's signing key.
   *
   * @return a path to the keystore file; or <code>null</code> if not set
   */
  String getSigningKeystorePath();

  /**
   * Returns the configured value for the type of the keystore holding the Gateway's signing key.
   *
   * @return a keystore type
   */
  String getSigningKeystoreType();

  String getSigningKeyAlias();

  /**
   * Returns the configured value for the alias name to use when to looking up the Gateway's signing
   * keystore's password.
   *
   * @return an alias name
   */
  String getSigningKeystorePasswordAlias();

  /**
   * Returns the configured value for the alias name to use when to looking up the signing key's
   * password.
   *
   * @return an alias name
   */
  String getSigningKeyPassphraseAlias();


  List<String> getGlobalRulesServices();

  /**
   * Returns true if websocket feature enabled else false.
   * Default is false.
   * @since 0.10
   * @return true if websocket feature is enabled
   */
  boolean isWebsocketEnabled();

  /**
   * Websocket connection max text message size.
   * @since 0.10
   * @return max text message size
   */
  int getWebsocketMaxTextMessageSize();

  /**
   * Websocket connection max binary message size.
   * @since 0.10
   * @return max binary message size
   */
  int getWebsocketMaxBinaryMessageSize();

  /**
   * Websocket connection max text message buffer size.
   * @since 0.10
   * @return buffer size
   */
  int getWebsocketMaxTextMessageBufferSize();

  /**
   * Websocket connection max binary message buffer size.
   * @since 0.10
   * @return buffer size
   */
  int getWebsocketMaxBinaryMessageBufferSize();

  /**
   * Websocket connection input buffer size.
   * @since 0.10
   * @return buffer size
   */
  int getWebsocketInputBufferSize();

  /**
   * Websocket connection async write timeout.
   * @since 0.10
   * @return timeout
   */
  int getWebsocketAsyncWriteTimeout();

  /**
   * Websocket connection idle timeout.
   * @since 0.10
   * @return timeout
   */
  int getWebsocketIdleTimeout();

  /**
   * Max count of messages that can be temporarily buffered in memory before a connection is properly setup.
   * @since 0.10
   * @return buffer size
   */
  int getWebsocketMaxWaitBufferCount();

  boolean isMetricsEnabled();

  boolean isJmxMetricsReportingEnabled();

  boolean isGraphiteMetricsReportingEnabled();

  String getGraphiteHost();

  int getGraphitePort();

  int getGraphiteReportingFrequency();

  /**
   * Enable cookie scoping to gateway path
   *
   * @return true if cookie scoping to path is enabled
   * @since 0.13
   */
  boolean isCookieScopingToPathEnabled();

  /**
   * Configured name of the HTTP Header that is expected
   * to be set by a proxy in front of the gateway.
   * @return header name
   */
  String getHeaderNameForRemoteAddress();

  /**
   * Configured Algorithm name to be used by the CryptoService
   * and MasterService implementations
   * @return algorithm
   */
  String getAlgorithm();

  /**
   * Configured Algorithm name to be used by the CryptoService
   * for password based encryption
   * @return algorithm
   */
  String getPBEAlgorithm();

  /**
   * Configured Transformation name to be used by the CryptoService
   * and MasterService implementations
   * @return transformation name
   */
  String getTransformation();

  /**
   * Configured SaltSize to be used by the CryptoService
   * and MasterService implementations
   * @return salt size
   */
  String getSaltSize();

  /**
   * Configured IterationCount to be used by the CryptoService
   * and MasterService implementations
   * @return iteration count
   */
  String getIterationCount();

  /**
   * Configured KeyLength to be used by the CryptoService
   * and MasterService implementations
   * @return key length
   */
  String getKeyLength();

  /**
   * Map of Topology names and their ports.
   * @return Map of Topology names and their ports.
   */
  Map<String, Integer> getGatewayPortMappings();

  /**
   * Is the Port Mapping feature on
   * @return true if port mapping enabled
   */
  boolean isGatewayPortMappingEnabled();

  /**
   * Is the Server header suppressed
   * @return turn if server header enabled
   */
  boolean isGatewayServerHeaderEnabled();

  /**
   * Determine the default address for discovering service endpoint details.
   *
   * @return A valid discovery source address, or null (because this property is optional).
   */
  String getDefaultDiscoveryAddress();

  /**
   * Determine the default target cluster for discovering service endpoint details.
   *
   * @return A valid cluster name, or null (because this property is optional).
   */
  String getDefaultDiscoveryCluster();

  /**
   *
   * @param type The type of cluster configuration monitor for which the interval should be returned.
   *
   * @return The polling interval configuration value, or -1 if it has not been configured.
   */
  int getClusterMonitorPollingInterval(String type);

  /**
   *
   * @param type The type of cluster configuration monitor for which the interval should be returned.
   *
   * @return The enabled status of the specified type of cluster configuration monitor.
   */
  boolean isClusterMonitorEnabled(String type);

  /**
   * @return The list of the names of any remote registry configurations defined herein.
   */
  List<String> getRemoteRegistryConfigurationNames();

  /**
   *
   * @param name The name of the remote registry configuration
   *
   * @return The configuration associated with the specified name.
   */
  String getRemoteRegistryConfiguration(String name);

  /**
   *
   * @return The name of a remote configuration registry client
   */
  String getRemoteConfigurationMonitorClientName();

  /**
   * When new remote registry entries must be created, or new ACLs applied to existing entries, this method indicates
   * whether unauthenticated connections should be given read access to those entries.
   *
   * @return true, if unauthenticated clients should be allowed to access remote registry entries.
   */
  boolean allowUnauthenticatedRemoteRegistryReadAccess();

  /**
   * Returns whether the Remote Alias Service is enabled or not.
   *
   * This value also depends on whether the remote configuration registry is enabled or not.
   * If it is enabled, then this option takes effect, else this option has no effect.
   *
   * @return true, if the remote alias service is enabled; otherwise, false;
   */
  boolean isRemoteAliasServiceEnabled();

  /**
   * Returns prefix for the remote alias service configuration
   *
   * @return the prefix for the remote alias service configuration
   */
  String getRemoteAliasServiceConfigurationPrefix();

  /**
   * Uses result of getRemoteAliasServiceConfigurationPrefix to return configurations
   *
   * @return Map of configurations that apply to the remote alias service
   */
  Map<String, String> getRemoteAliasServiceConfiguration();

  /**
   * Get the list of those topology names which should be treated as read-only, regardless of their actual read-write
   * status.
   *
   * @return A list of the names of those topologies which should be treated as read-only.
   */
  List<String> getReadOnlyOverrideTopologyNames();

  /**
   * Get the comma separated list of group names that represent Knox Admin users
   * @return comma separate list of admin group names
   */
  String getKnoxAdminGroups();

  /**
   * Get the comma separated list of user names that represent Knox Admin users
   * @return comma separated list of admin user names
   */
  String getKnoxAdminUsers();

  /**
   * Custom header name to be used to pass the authenticated principal
   * via dispatch
   * @since 1.1.0
   * @return federation header
   */
  String getFederationHeaderName();

  /**
   * Get the list of topology names that should be redeployed on restart.
   * manager and admin are default topologies as they may depend on gateway-site.xml
   * configuration for deployment time config.
   * @return list of topology names
   */
  List<String> getAutoDeployTopologyNames();

  /*
   * Get the semicolon-delimited set of regular expressions defining to which hosts Knox will permit requests to be
   * dispatched.
   *
   * @return The whitelist, which will be null if none is configured (in which case, requests to any host are permitted).
   */
  String getDispatchWhitelist();

  /**
   * Get the set of service roles to which the dispatch whitelist will be applied.
   *
   * @return The service roles, or an empty list if none are configured.
   */
  List<String> getDispatchWhitelistServices();

  /**
   * Returns true when strict topology validation is enabled,
   * in which case if topology validation fails Knox will throw
   * a runtime exception. If false and topology validation fails
   * Knox will log an ERROR and move on.
   *
   * @since 1.1.0
   * @return true if topology validation enabled
   */
  boolean isTopologyValidationEnabled();

  /**
   * @return true if topology re-deployment requires an actual change in the
   *         topology. Defaults to <code>false</code> to be backward compatible
   *         with previous chanages.
   *
   * @since 2.0.0
   */
  boolean topologyRedeploymentRequiresChanges();

  /**
   * Returns a list of services that need service name appended to
   * X-Forward-Context header as a result of which the new header would look
   * /{gateway}/{sandbox}/{serviceName}
   *
   * @return List of service names for which service name needs to be appended
   * to X-Forward-Context header, can be empty list.
   * @since 1.3.0
   */
  List<String> getXForwardContextAppendServices();

  /**
   * Returns a set of service principal names that indicate which services to ignore doAs requests.
   * <p>
   * If a service in the returned set sends a Kerberos-authenticated request to the Gateway, the doAs
   * query parameter is to be ignored; thus leaving the authenticated user details intact.
   * <p>
   * If the (authenticated) service is not authorized to set the specified proxy user (see information
   * related to hadoop.proxyuser.... properties) an error will not be returned since the request to
   * impersonate users is to be ignored.
   *
   * @return a set of service principal names that indicate which services to ignore doAs request
   */
  Set<String> getServicesToIgnoreDoAs();

  /**
   * @return the monitoring interval (in milliseconds) of Cloudera Manager descriptors
   */
  long getClouderaManagerDescriptorsMonitoringInterval();

  /**
   * @return the monitoring interval (in milliseconds) of Cloudera Manager advanced service discovery configuration
   */
  long getClouderaManagerAdvancedServiceDiscoveryConfigurationMonitoringInterval();

  /**
   * @return true, if state for tokens issued by the Knox Token service should be managed by Knox.
   */
  boolean isServerManagedTokenStateEnabled();


  /**
   * Return the configured interval (in seconds) at which token eviction job should run
   * @return eviction job run interval in seconds
   */
  long getKnoxTokenEvictionInterval();

  /**
   * Return the configured grace period (in seconds) after which an expired token should be evicted
   * @return eviction grace period in seconds
   */
  long getKnoxTokenEvictionGracePeriod();

  /**
   * Return the configured token state alias persistence interval (in seconds).
   * @return Token state alias persistence interval in seconds.
   */
  long getKnoxTokenStateAliasPersistenceInterval();

  /**
   * @return the HMAC algorithm name to be used to sign generated Knox Token content (e.g. the token.id claim)
   */
  String getKnoxTokenHashAlgorithm();

  /**
   * @return the maximum number of tokens a user can manage at the same time. -1
   *         means that users are allowed to create/manage as many tokens as they
   *         want. This configuration only applies when server-managed token state
   *         is enabled either in gateway-site or at the topology level.
   */
  int getMaximumNumberOfTokensPerUser();

  /**
   * @return the list of topologies that should be hidden on Knox homepage
   */
  Set<String> getHiddenTopologiesOnHomepage();

  /**
   * @return the list of pinned topologies on Knox homepage
   */
  Set<String> getPinnedTopologiesOnHomepage();

  /**
   * @return returns whether know token permissive validation is enabled
   */
  boolean isKnoxTokenPermissiveValidationEnabled();

  /**
   * @param service Service to get the parameter for.
   * @param parameter Parameter key to get the value for.
   *
   * @return the value of the given parameter for the given service if declared; an empty String otherwise
   */
  String getServiceParameter(String service, String parameter);

  /**
   * @return the whether logout from the knox home page is enabled or not
   */
  boolean homePageLogoutEnabled();

  /**
   * @return the Global Logout Page for Federated IDPs
   */
  String getGlobalLogoutPageUrl();

  /**
   * @return the maximum number of cache entries where keystore entries are stored
   */
  long getKeystoreCacheSizeLimit();

  /**
   * @return the time - in minutes - an entry should be live (i.e. must not expire) in keystore cache
   */
  long getKeystoreCacheEntryTimeToLiveInMinutes();

  /**
   * Indicates whether the embedded Jetty Server support for X-Forwarded Headers should
   * be enabled.
   * @return true if incoming X-Forwarded headers are enabled
   */
  boolean isGatewayServerIncomingXForwardedSupportEnabled();

  /**
   * Gets the home page profiles (pre-configured and user-defined profiles too).
   * It's important that keys in the returned map are converted to lowercase strings.
   */
  Map<String, Collection<String>> getHomePageProfiles();

  String getDatabaseType();

  String getDatabaseConnectionUrl();

  String getDatabaseHost();

  int getDatabasePort();

  String getDatabaseName();

  boolean isDatabaseSslEnabled();

  boolean verifyDatabaseSslServerCertificate();

  String getDatabaseSslTruststoreFileName();

}
